package xin.marcher.module.lifecycle.service.impl;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import xin.marcher.module.common.constants.construction.ProductConstants;
import xin.marcher.module.common.core.PageResult;
import xin.marcher.module.common.enums.lifecycle.ItemExpriEnum;
import xin.marcher.module.common.enums.lifecycle.MarketExpriResultEnum;
import xin.marcher.module.common.exception.BaseBizException;
import xin.marcher.module.common.utils.DateFormatUtil;
import xin.marcher.module.lifecycle.domain.dto.*;
import xin.marcher.module.lifecycle.domain.entity.ItemPeriodStageDO;
import xin.marcher.module.lifecycle.domain.request.ItemExpriReslutPageRequest;
import xin.marcher.module.lifecycle.domain.request.ItemPeriodRequest;
import xin.marcher.module.lifecycle.domain.request.ItemPeriodStagePageQueryRequest;
import xin.marcher.module.lifecycle.domain.request.QueryPeriodListRequest;
import xin.marcher.module.lifecycle.domain.response.ItemPeriodStageResponse;
import xin.marcher.module.lifecycle.repository.ItemPeriodStageRepository;
import xin.marcher.module.lifecycle.service.ItemPeriodStageService;

import javax.annotation.Resource;
import java.util.*;

/**
 *
 */
@Slf4j
@Service
public class ItemPeriodStageServiceImpl implements ItemPeriodStageService {

    @Resource
    private ItemPeriodStageRepository itemPeriodStageRepository;

    /**
     * 模拟数据
     */
    public static Map<Long, ItemExpriResultDTO> itemPeriodStageMap = new HashMap<Long, ItemExpriResultDTO>() {{
        put(100000476748L, new ItemExpriResultDTO("100000476748", 121, 1, "", 1, 1, 1, new Date()));
        put(100000574536L, new ItemExpriResultDTO("100000574536", 121, 1, "", 1, 1, 1, new Date()));
        put(100000600583L, new ItemExpriResultDTO("100000600583", 121, 1, "", 1, 1, 1, new Date()));
        put(100000626630L, new ItemExpriResultDTO("100000626630", 121, 1, "", 1, 1, 1, new Date()));
        put(100000704772L, new ItemExpriResultDTO("100000704772", 121, 1, "", 1, 1, 1, new Date()));
        put(100000756866L, new ItemExpriResultDTO("100000756866", 121, 1, "", 1, 1, 1, new Date()));
    }};

    /**
     * 创建商品状态及商品生命周期状态
     *
     * @param itemPeriodRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ItemPeriodStageResultDTO saveItemPeriodStage(ItemPeriodRequest itemPeriodRequest) {
        itemPeriodStageRepository.saveItemPeriodStage(itemPeriodRequest);
        return new ItemPeriodStageResultDTO(Boolean.TRUE);
    }

    /**
     * 根据itemId查询商品生命周期可采可补可售结果
     *
     * @param itemId
     * @return
     */
    @Override
    public ItemExpriResultDTO queryItemExpriResultByItemId(String itemId) {
        return itemPeriodStageRepository.queryItemExpriResultByItemId(itemId);
    }

    /**
     * 分页查询商品生命周期数据
     *
     * @param request
     * @return
     */
    @Override
    public PageResult<ItemPeriodStageDTO> queryItemPeriodStageByPage(ItemPeriodStagePageQueryRequest request) {
        return itemPeriodStageRepository.queryItemPeriodStageByPage(request);
    }

    /**
     * 根据itemId查询商品生命周期状态
     *
     * @param itemId
     * @return
     */
    @Override
    public ItemPeriodStageDTO queryProductPeriod(String itemId) {
        return itemPeriodStageRepository.queryProductPeriod(itemId);
    }

    /**
     * 更新商品生命周期状态
     *
     * @param itemPeriodStageDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ItemPeriodStageResponse updateProductPeriod(ItemPeriodStageDTO itemPeriodStageDTO) {
        // 1.先查询出这条生命周期状态记录
        ItemPeriodStageDO itemPeriodStageDO = itemPeriodStageRepository
                .queryProductPeriod(itemPeriodStageDTO);
        log.info("生命周期状态：{}", JSON.toJSONString(itemPeriodStageDTO));
        // 2.判断是否存在记录
        if (Objects.isNull(itemPeriodStageDO)) {
            return new ItemPeriodStageResponse(Boolean.FALSE, "选择修改的记录不存在");
        }
        log.info("生命周期状态：{}", JSON.toJSONString(itemPeriodStageDO));
        // 3.判读是否允许修改
        if ((itemPeriodStageDTO.getPeriodStage() - itemPeriodStageDO.getPeriodStage()) < 0) {
            return new ItemPeriodStageResponse(Boolean.FALSE, "不能逆向修改商品生命周期状态");
        }
        // 3.更新生命周期状态
        itemPeriodStageRepository.updateProductPeriod(itemPeriodStageDO, itemPeriodStageDTO);
        return new ItemPeriodStageResponse();
    }

    /**
     * 更新商品生命周期考核结果&可采可补可售状态
     *
     * @param itemPeriodStageDetailDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateProductPeriodMarketExpri(ItemPeriodStageDetailDTO itemPeriodStageDetailDTO) {
        return itemPeriodStageRepository.updateProductPeriodMarketExpri(itemPeriodStageDetailDTO);
    }

    /**
     * 根据商品itemIds查询商品生命周期信息
     *
     * @param request
     * @return
     */
    @Override
    public List<ItemExpriResultDTO> queryItemExpriResult(QueryPeriodListRequest request) {
        return itemPeriodStageRepository.queryItemExpriResultByItemIds(request);
    }

    /**
     * 分页查询商品考核结果
     *
     * @param request
     * @return
     */
    @Override
    public PageResult<ItemExpriResultDTO> queryItemExpriResultByPage(ItemExpriReslutPageRequest request) {
        return itemPeriodStageRepository.queryItemExpriResultByPage(request);
    }

    /**
     * 分页批量查询商品考核结果
     *
     * @param request
     * @return
     */
    @Override
    public List<ItemExpriResultToExcelDTO> queryItemExpriResultBatch(ItemExpriReslutPageRequest request) {
        // 查询考核结果每次的数据量可能会比较大，所以预设一个较大的List初始大小，避免多次扩容
        List<ItemExpriResultDTO> results = new ArrayList<>(ProductConstants.QUERY_ITEM_MAX_COUNT * 10);
        // 1、设置每次查询的数据量，最大为200
        request.setPageSize(ProductConstants.QUERY_ITEM_MAX_COUNT);
        Integer pageNum = request.getPageNum();
        List<ItemExpriResultDTO> batchResult;
        try {
            while (true) {
                // 2、分页数据
                log.info("request:{}", JSON.toJSONString(request));
                PageResult<ItemExpriResultDTO> page = itemPeriodStageRepository
                        .queryItemExpriResultByPage(request);
                // 3、判断是否还有数据，还有数据则页码+1继续执行分页查询
                log.info("page:{}", JSON.toJSONString(page));
                if (Objects.isNull(page) || CollectionUtils.isEmpty(page.getContent())) {
                    break;
                }
                // 4.拿到本次查询的数据
                batchResult = page.getContent();
                log.info("dataList:{}", JSON.toJSONString(batchResult));
                // 判断拿到的数据是否为空，或为null，若为空或为null，说明本次查询未查到数据，可直接break
                if (CollectionUtils.isEmpty(batchResult)) {
                    break;
                }
                // 6.查询到的数据全部加入到返回的结果集中，页码+1
                results.addAll(batchResult);
                request.setPageNum(++pageNum);
                // 每次循环获取数据后，休眠20ms，避免对数据库造成太大压力
                Thread.sleep(20);
            }
        } catch (InterruptedException e) {
            throw new BaseBizException("查询出错，request:{}", JSON.toJSONString(request));
        }
        log.info("result:{}", results);
        // 7、返回转换后的结果集
        return transferItemExpriResultToExcelDTO(results);
    }

    /**
     * 数据转换
     *
     * @param list
     * @return
     */
    private List<ItemExpriResultToExcelDTO> transferItemExpriResultToExcelDTO(
            List<ItemExpriResultDTO> list) {
        List<ItemExpriResultToExcelDTO> result = new ArrayList<>(list.size());
        ItemExpriResultToExcelDTO itemExpriResultToExcelDTO;
        // 循环处理为导出对象内容
        for (ItemExpriResultDTO expriResultDTO : list) {
            itemExpriResultToExcelDTO = ItemExpriResultToExcelDTO.builder()
                    .categoryId(expriResultDTO.getCategoryId())
                    .itemId(expriResultDTO.getItemId())
                    .marketExpriResultDesc(expriResultDTO.getMarketExpriResultDesc())
                    .updateTime(DateFormatUtil.format(expriResultDTO.getUpdateTime()))
                    .marketExpriResult(MarketExpriResultEnum.getByCode(expriResultDTO.getMarketExpriResult()).getValue())
                    .purchaseStatus(ItemExpriEnum.getByCode(expriResultDTO.getPurchaseStatus()).getValue())
                    .replenishmentStatus(ItemExpriEnum.getByCode(expriResultDTO.getReplenishmentStatus()).getValue())
                    .saleStatus(ItemExpriEnum.getByCode(expriResultDTO.getSaleStatus()).getValue())
                    .build();
            result.add(itemExpriResultToExcelDTO);
        }
        return result;
    }
}
